const { Report } = require('../../models');
const fs = require('fs');
const fsp = require('fs').promises; 
const path = require('path');
const natural = require('natural');
const { exec } = require('child_process');
const pdfParse = require('pdf-parse');
const mammoth = require('mammoth');
const axios = require('axios');
const jieba = require('nodejieba');

const uploadDir = path.join(__dirname, '../../uploads');
if (!fs.existsSync(uploadDir)) {
    fs.mkdirSync(uploadDir, { recursive: true });
}

class ReportController {
    // 上传报告并存储路径
    async uploadReport(req, res) {
        try {
            if (!req.file) {
                return res.status(400).send({ message: '未上传报告文件' });
            }
    
            const originalFilePath = path.join(uploadDir, req.file.filename);
            const fileExtension = path.extname(req.file.originalname).toLowerCase();
    
            // 直接保存上传的文件路径
            const savedFilePath = `/uploads/${req.file.filename}`;
    
            // 存储文件路径到数据库
            const report = await Report.create({
                name: req.file.originalname, // 保存原始文件名
                path: savedFilePath,        // 保存文件路径
                uploadedAt: new Date(),
            });
    
            res.send({ message: '报告上传成功', report });
        } catch (error) {
            console.error('上传报告失败:', error);
            res.status(500).send({ message: '上传报告失败' });
        }
    }

    // 从数据库获取报告列表
    async getReports(req, res) {
        try {
            const reports = await Report.findAll(); // 从数据库获取报告列表
            res.send({ message: '获取报告列表成功', reports });
        } catch (error) {
            console.error('获取报告列表失败:', error);
            res.status(500).send({ message: '获取报告列表失败' });
        }
    }

    // 删除报告
    async deleteReport(req, res) {
        try {
            console.log('收到删除请求，ID:', req.params.id);
            const { id } = req.params;

            // 查找报告记录
            const report = await Report.findByPk(id);
            if (!report) {
                return res.status(404).send({ message: '报告不存在' });
            }

            // 删除本地文件
            const filePath = path.join(__dirname, '../../', report.path);
            if (fs.existsSync(filePath)) {
                fs.unlinkSync(filePath); // 删除文件
            }

            // 删除数据库记录
            await report.destroy();

            res.send({ message: '报告删除成功' });
        } catch (error) {
            console.error('删除报告失败:', error);
            res.status(500).send({ message: '删除报告失败', error: error.message });
        }
    }

    // 查重功能
    async checkDuplicates(req, res) {
        try {
            console.log('开始查询报告列表');
            const reports = await Report.findAll();
            console.log(`查询到 ${reports.length} 份报告`);
            if (reports.length < 2) {
                console.log('报告数量不足，无法进行查重');
                return res.status(400).send({ message: '报告数量不足，无法进行查重' });
            }

            // 异步读取文件内容
            const fileContents = {};
            const failedFiles = [];
            for (const report of reports) {
                const filePath = path.join(__dirname, '../../', report.path);
                const fileExtension = path.extname(filePath).toLowerCase();

                try {
                    console.log(`开始读取文件: ${filePath}`);
                    if (fileExtension === '.pdf') {
                        const pdfBuffer = await fsp.readFile(filePath);
                        const pdfData = await pdfParse(pdfBuffer);
                        const pdfText = pdfData.text.trim();
                        if (pdfText.length === 0) {
                            console.warn(`文件 ${filePath} 内容为空，跳过`);
                            failedFiles.push({ id: report.id, message: '文件内容为空' });
                            continue;
                        }
                        fileContents[report.id] = pdfText;

                        if (pdfData.warnings && pdfData.warnings.length > 0) {
                            console.warn(`解析 ${filePath} 时的警告:`, pdfData.warnings);
                        }
                    } else if (fileExtension === '.docx') {
                        const docxBuffer = await fsp.readFile(filePath);
                        const docxData = await mammoth.extractRawText({ buffer: docxBuffer });
                        const docxText = docxData.value.trim();
                        if (docxText.length === 0) {
                            console.warn(`文件 ${filePath} 内容为空，跳过`);
                            failedFiles.push({ id: report.id, message: '文件内容为空' });
                            continue;
                        }
                        fileContents[report.id] = docxText;

                        if (docxData.messages && docxData.messages.length > 0) {
                            console.warn(`解析 ${filePath} 时的警告:`, docxData.messages);
                        }
                    } else if (fileExtension === '.txt') {
                        const txtText = (await fsp.readFile(filePath, 'utf-8')).trim();
                        if (txtText.length === 0) {
                            console.warn(`文件 ${filePath} 内容为空，跳过`);
                            failedFiles.push({ id: report.id, message: '文件内容为空' });
                            continue;
                        }
                        fileContents[report.id] = txtText;
                    } else {
                        console.warn(`跳过不支持的文件类型: ${filePath}`);
                        failedFiles.push({ id: report.id, message: '文件类型不支持' });
                        continue;
                    }
                    console.log(`成功读取文件: ${filePath}`);
                } catch (err) {
                    console.error(`读取文件失败: ${filePath}`, err);
                    failedFiles.push({ id: report.id, message: '文件读取失败' });
                }
            }

            // 若有效报告数量少于 2 份，返回错误
            const validReportIds = Object.keys(fileContents);
            console.log(`有效报告数量: ${validReportIds.length}`);
            if (validReportIds.length < 2) {
                console.log('有效报告数量不足，无法进行查重');
                return res.status(400).send({ message: '有效报告数量不足，无法进行查重' });
            }

            // 分词并统计词频
            const jieba = require('nodejieba'); // 引入中文分词库
            const tokenizer = (text) => jieba.cut(text.toLowerCase()); // 中文分词函数
            const termFrequencyMaps = {};
            console.log('开始分词并统计词频');
            validReportIds.forEach(id => {
                const tokens = tokenizer(fileContents[id]);
                // console.log(`报告ID ${id} 的分词结果前10个: ${tokens.slice(0, 10).join(', ')}`); // 输出分词示例
                termFrequencyMaps[id] = tokens.reduce((acc, token) => {
                    acc[token] = (acc[token] || 0) + 1;
                    return acc;
                }, {});
                // console.log(`报告ID ${id} 的词频统计示例: ${JSON.stringify(Object.entries(termFrequencyMaps[id]).slice(0, 5))}`); // 输出词频示例
            });
            console.log('完成分词并统计词频');

            // 计算相似度矩阵
            const similarityMatrix = [];
            console.log('开始计算相似度矩阵');
            for (let i = 0; i < validReportIds.length; i++) {
                similarityMatrix[i] = [];
                for (let j = 0; j < validReportIds.length; j++) {
                    if (i === j) {
                        similarityMatrix[i][j] = 1;
                    } else {
                        const vec1 = termFrequencyMaps[validReportIds[i]];
                        const vec2 = termFrequencyMaps[validReportIds[j]];
                        const allTerms = new Set([...Object.keys(vec1), ...Object.keys(vec2)]);
                        let dotProduct = 0;
                        let norm1 = 0;
                        let norm2 = 0;

                        allTerms.forEach(term => {
                            const a = vec1[term] || 0;
                            const b = vec2[term] || 0;
                            dotProduct += a * b;
                            norm1 += a * a;
                            norm2 += b * b;
                        });

                        const denominator = Math.sqrt(norm1) * Math.sqrt(norm2);
                        const similarity = denominator === 0 ? 0 : dotProduct / denominator;
                        if (denominator === 0) {
                            console.warn(`报告ID ${validReportIds[i]} 与 ${validReportIds[j]} 向量范数为零，相似度设为0`);
                        }
                        similarityMatrix[i][j] = similarity;
                    }
                }
            }
            console.log('完成计算相似度矩阵');

            // 构建结果对象，包含原始报告信息和失败文件信息
            const resultReports = reports.map(report => ({
                ...report.get({ plain: true }),
                similarity: validReportIds.includes(report.id.toString()) 
                    ? similarityMatrix[validReportIds.indexOf(report.id.toString())] 
                    : null
            }));

            console.log('准备返回查重结果');
            // 输出详细查重结果
            const resultLog = resultReports.map(report => 
                `报告ID: ${report.id}, 名称: ${report.name}, 相似度: ${report.similarity?.join(', ')}`
            ).join('; ');
            console.log(`准备返回查重结果：${resultLog}`);
            res.send({
                message: '查重完成',
                similarityMatrix,
                reports: resultReports,
                failedFiles
            });
        } catch (error) {
            console.error('查重失败:', error);
            res.status(500).send({ message: '查重失败', error: error.message });
        }
    }

    // 生成摘要功能
    async generateSummary(req, res) {
        try {
            const { id } = req.params;
            const report = await Report.findByPk(id);
            if (!report) {
                return res.status(404).send({ message: '报告不存在' });
            }
            const filePath = path.join(__dirname, '../../', report.path);
            const fileExtension = path.extname(filePath).toLowerCase();
            let text = '';

            if (fileExtension === '.pdf') {
                const pdfBuffer = await fsp.readFile(filePath);
                const pdfData = await pdfParse(pdfBuffer);
                text = pdfData.text;
            } else if (fileExtension === '.docx') {
                const docxBuffer = await fsp.readFile(filePath);
                const docxData = await mammoth.extractRawText({ buffer: docxBuffer });
                text = docxData.value;
            } else if (fileExtension === '.txt') {
                text = await fsp.readFile(filePath, 'utf-8');
            } else {
                return res.status(400).send({ message: '不支持的文件类型' });
            }

            // 调用 DeepSeek API 生成摘要
            const apiKey = process.env.DEEPSEEK_API_KEY;
            const deepseekRes = await axios.post(
                'https://api.deepseek.com/v1/chat/completions',
                {
                    model: 'deepseek-chat',
                    messages: [
                        { role: 'system', content: '你是一个实验报告摘要助手，请帮我对下面的内容生成简明摘要。' },
                        { role: 'user', content: text.slice(0, 4000) }
                    ]
                },
                {
                    headers: {
                        'Authorization': `Bearer ${apiKey}`,
                        'Content-Type': 'application/json'
                    }
                }
            );

            const summary = deepseekRes.data.choices?.[0]?.message?.content || '未获取到摘要';
            // 更新数据库
            report.summary = summary;
            await report.save();
            res.send({ summary });
        } catch (error) {
            console.error('生成摘要失败:', error);
            res.status(500).send({ message: '生成摘要失败', error: error.message });
        }
    }
}

module.exports = new ReportController();